"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : cm_install
Case Name   : cm_install指定-e参数路径错误
Create At   : 2022/11/15
Owner       : opentestcase012
Description :
    1: 配置xml文件中的cm相关参数;
    2: 数据库用户下执行cm_install,指定-e参数路径错误;
    3: gs_om查看集群状态;
    4: cm_ctl查看集群状态;
    5: 查看数据库用户下进程和定时任务;
Expect      :
    1: 成功
    2: 安装失败
    3: 数据库状态正常,未安装cm
    4: 失败,未安装cm
    5: 无om_monitor、cm_agent、cm_server的进程，无定时任务
History     :
    modified by opentestcase034 at 2023-6-2:修改为使用root用户拷贝xml文件
"""
import os
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro

Primary_SH = CommonSH('PrimaryDbUser')


@unittest.skipIf(3 != Primary_SH.get_node_num(), '需1主2备环境，否则不执行')
class Tools(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.pri_user = Node('PrimaryDbUser')
        self.pri_root = Node('PrimaryRoot')
        self.primary_sh = CommonSH('PrimaryDbUser')
        self.sta1_user = Node('Standby1DbUser')
        self.sta1_root = Node('Standby1Root')
        self.sta2_user = Node('Standby2DbUser')
        self.sta2_root = Node('Standby2Root')
        self.common = Common()
        self.constant = Constant()
        self.cm_tool = os.path.join(macro.DB_INSTANCE_PATH, '..', 'app',
                                    'tool', 'cm_tool')
        self.cm_dir = os.path.join(macro.DB_INSTANCE_PATH, '..', 'cm')
        self.cm_xml = os.path.join(os.path.dirname(macro.DB_XML_PATH),
                                   'cm.xml')
        env1 = os.path.join(os.path.dirname(macro.DB_ENV_PATH),
                            'error_env')
        env2 = os.path.dirname(macro.DB_ENV_PATH)
        self.env_msg = {
            env1: f"[GAUSS-50201] : The envFile {env1} does not exist",
            env2: f"[GAUSS-50210] : The envFile {env2} must be a file"}

    def test_standby(self):
        text = '-----查看主机名-----'
        self.log.info(text)
        host_pri = self.common.get_sh_result(self.pri_root, "uname -n")
        host_sta1 = self.common.get_sh_result(self.sta1_root, "uname -n")
        host_sta2 = self.common.get_sh_result(self.sta2_root, "uname -n")
        self.assertIsNotNone(host_pri and host_sta1 and host_sta2,
                             '执行失败:' + text)
        hosts = f"{host_pri},{host_sta1},{host_sta2}"
        node_ip = f"{self.pri_user.db_host},{self.sta1_user.db_host}," \
            f"{self.sta2_user.db_host}"
        match_pri = f'value="{host_pri}"'
        match_sta1 = f'value="{host_sta1}"'
        match_sta2 = f'value="{host_sta2}"'

        self.log.info('-----查询系统和数据库版本-----')
        os_cpu = self.pri_root.sh('cat /etc/*release;'
                                  'uname -a').result()
        self.log.info(os_cpu)
        find_cmd = f'source {macro.DB_ENV_PATH};' \
            f'gaussdb -V'
        find_ver_msg = self.common.get_sh_result(self.pri_user, find_cmd)
        assert find_ver_msg.find('compiled at') > -1
        db_release_version = find_ver_msg.split()[2]

        self.log.info('-----获取cm压缩包路径,赋予普通用户执行权限-----')
        cm_tgz = ''
        if 'CentOS Linux 7' in os_cpu:
            cm_tgz = f'openGauss-{db_release_version}-CentOS-64bit-cm.tar.gz'
        elif 'openEuler 20.03' in os_cpu:
            cm_tgz = f'openGauss-{db_release_version}-openEuler-64bit-cm.tar.gz'
        cmpkg_old = os.path.join(os.path.dirname(macro.DB_SCRIPT_PATH), cm_tgz)
        cmpkg = os.path.join(macro.DB_INSTANCE_PATH, cm_tgz)
        cmd = f'cp {cmpkg_old} {cmpkg};' \
            f'chown -R {self.pri_user.ssh_user}:{self.pri_user.ssh_user} ' \
            f'{cmpkg};'
        res = self.common.get_sh_result(self.pri_root, cmd)
        self.assertEqual('', res, '执行失败:' + text)

        text = '-----查询系统未使用端口-----'
        self.log.info(text)
        global port
        for count in range(10):
            port = self.common.get_not_used_port(self.pri_root)
            self.log.info(port)
            standby_port_check_cmd = f'netstat -tlnp | grep {port}'
            sta1_check_msg = self.common.get_sh_result(self.sta1_root,
                                                       standby_port_check_cmd)
            sta2_check_msg = self.common.get_sh_result(self.sta2_root,
                                                       standby_port_check_cmd)
            if not (sta1_check_msg and sta2_check_msg):
                self.assertNotEqual(0, port, '执行失败:' + text)
                break
            else:
                continue

        text = '-----step1:配置xml文件中的cm相关参数; expect:成功-----'
        self.log.info(text)
        cminfo_pri = f'\\r\\n            ' \
            f'<PARAM name="cmDir" value="{self.cm_dir}"/>\\r\\n            ' \
            f'<PARAM name="cmsNum" value="1"/>\\r\\n            ' \
            f'<PARAM name="cmServerPortBase" value="{port}"/>\\r\\n' \
            f'            <PARAM name="cmServerPortStandby" value="{port}"/>' \
            f'\\r\\n            ' \
            f'<PARAM name="cmServerlevel" value="1"/>\\r\\n            ' \
            f'<PARAM name="cmServerListenIp1" value="{node_ip}"/>' \
            f'\\r\\n            ' \
            f'<PARAM name="cmServerRelation" value="{hosts}"/>\\r\\n'
        cminfo_sta = f'            <PARAM name="cmDir" value="{self.cm_dir}"/>'
        sed_cmd = f"cp {macro.DB_XML_PATH} {self.cm_xml};" \
            f"sed -i '/{match_pri}/a\\{cminfo_pri}' {self.cm_xml};" \
            f"sed -i '/{match_sta1}/a\\{cminfo_sta}' {self.cm_xml};" \
            f"sed -i '/{match_sta2}/a\\{cminfo_sta}' {self.cm_xml};" \
            f"cat {self.cm_xml};" \
            f"chown -R {self.pri_user.ssh_user}:{self.pri_user.ssh_user} " \
            f"{self.cm_xml};"
        self.log.info(sed_cmd)
        sed_msg = self.common.get_sh_result(self.pri_root, sed_cmd)
        self.assertEqual(3, sed_msg.count(self.cm_dir), '执行失败:' + text)

        text = '-----step2:数据库用户下执行cm_install,指定-e参数路径错误 expect:安装失败-----'
        self.log.info(text)
        for env, error_msg in self.env_msg.items():
            install_cmd = f'cd {self.cm_tool};' \
                f'chmod +x cm_install;' \
                f'./cm_install -X {self.cm_xml} -e {env} ' \
                f'--cmpkg {cmpkg}'
            self.log.info(install_cmd)
            install_res = self.common.get_sh_result(self.pri_user, install_cmd)
            self.assertIn(error_msg, install_res, '执行失败:' + text)

        text = '-----step3:gs_om查看集群状态;expect: 数据库状态正常,未安装cm-----'
        self.log.info(text)
        status_msg = Primary_SH.get_db_cluster_status('detail')
        self.log.info(status_msg)
        self.assertIn(self.constant.CLUSTER_NORMAL_MSG, status_msg,
                      "执行失败:" + text)
        self.assertNotIn('CMServer State', status_msg, "执行失败:" + text)

        text = '-----step4:cm_ctl查看集群状态 expect:失败,未安装cm-----'
        self.log.info(text)
        show_status = f'source {macro.DB_ENV_PATH};' \
            f'cm_ctl query -Civdp'
        status_msg = self.common.get_sh_result(self.pri_user, show_status)
        self.assertIn("can't connect to cm_server", status_msg, "执行失败:" + text)

        text = '----step5:查看数据库用户下进程和定时任务 ' \
               'expect:无om_monitor、cm_agent、cm_server的进程，无定时任务----'
        self.log.info(text)
        show_cmd = "crontab -l;ps ux|egrep 'cm_server|cm_agent|om_monitor';"
        process_res = self.primary_sh.exec_gs_ssh(show_cmd)
        self.assertNotIn(process_res, 'bin/cm_server', "执行失败:" + text)
        self.assertNotIn(process_res, 'bin/cm_agent', "执行失败:" + text)
        self.assertNotIn(process_res, 'om_monitor -L', "执行失败:" + text)

    def tearDown(self):
        self.log.info('----清理环境----')
        text = '----删除xml文件; expect:删除成功----'
        self.log.info(text)
        rm_cmd = f'rm -rf {self.cm_xml};'
        self.log.info(rm_cmd)
        self.common.get_sh_result(self.pri_root, rm_cmd)
        check_cmd = f'if [[ -e {self.cm_xml} ]]; ' \
            f'then echo "exists"; else echo "not exists"; fi'
        rm_msg_pri = self.common.get_sh_result(self.pri_root, check_cmd)

        self.assertEqual('not exists', rm_msg_pri, '执行失败:' + text)
        self.log.info(f'-----{os.path.basename(__file__)} end-----')
